use std::collections::HashMap;

use error::{SmkError, SmkResult};

use crate::{MonitorPrinter, Protocol};

/// 监视器执行命令结果
///
/// `SmkResult` 别名
pub type MonResult<T> = SmkResult<T>;

/// 监视器执行命令错误
///
/// `SmkError` 别名
pub type MonError = SmkError;

/// readline 补全位置
pub enum CompleterPosFrom {
    /// 从最后一个参数的开始位置
    ///
    /// `Start(0) = Default`
    Start(usize),
    /// 从当前位置
    Current(isize),
    /// 默认从最后一个参数开始位置
    Deafult,
}

/// 补全建议
pub struct CompleterSuggestion {
    // 补全位置
    pub(crate) from: CompleterPosFrom,
    // 补全列表
    pub(crate) list: Vec<String>,
    // 是否在唯一的补全目标字符串最后附加 ' '
    pub(crate) append_whitespace: bool,
}

impl CompleterSuggestion {
    /// 创建 `CompleterSuggestion`
    pub fn create(from: CompleterPosFrom, list: Vec<String>, whitespace: bool) -> Self {
        Self { from, list, append_whitespace: whitespace }
    }
}

/// 监视器命令实现
///
/// 每个命令实现该 trait, `mon_readline_exec`, `mon_protocol_exec` 和 `mon_readline_help` 为必须实现类型
#[allow(unused_variables)]
pub trait MonitorCommand {
    /// 监视器参数类型匹配
    ///
    /// 类似如下形式:
    /// ```text
    /// "data1:s,data2:i,data3:f"
    /// ```
    /// * `i64` 为 i64 类型
    /// * `u64` 为 u64 类型
    /// * `isize` 为 isize 类型
    /// * `usize` 为 usize 类型
    /// * `f64` 为 f64 类型
    /// * `str` 为 string 类型
    /// * `bool` 为 bool 类型
    /// * `*` 为任意类型
    /// * 每个参数附加 `:[*｜str｜usize|...]?`, 表示该参数可选(注意: 使用`?`, 后续还有参数也必须是`?`)
    /// * 返回空字符串, 表示该命令不接受任何参数
    /// * 返回 None, 则不检查任何参数, 参数按照`"1","2","3"...`排序存放在 hashmap 中
    fn mon_readline_arg_type(&self) -> Option<&'static str> {
        None
    }

    /// 监视器 readline 补全
    ///
    /// args 按照 line 顺序排序, `is_space` 指示当前光标位置是否为空格
    fn mon_readline_completer(&self, args: &[&str], is_space: bool) -> Option<CompleterSuggestion> {
        None
    }

    /// 监视器 readline help 信息
    ///
    /// 简短的命令 help 信息
    fn mon_readline_help(&self) -> String;

    /// 监视器 readline help 长信息
    ///
    /// 详细的命令 help 信息
    fn mon_readline_long_help(&self) -> Option<String> {
        None
    }

    /// 监视器 readline 执行命令
    ///
    /// # Errors
    /// 实现者返回执行结果
    fn mon_readline_exec(
        &self,
        args: &HashMap<String, String>,
        printer: &MonitorPrinter,
    ) -> MonResult<()>;

    /// 监视器 smp 控制协议执行命令
    ///
    /// # Errors
    /// 实现者返回执行结果
    fn mon_protocol_exec(&self, args: &Protocol) -> MonResult<Protocol>;
}
